using UniversalAdmin.Application.Dto;
using UniversalAdmin.Domain.Entities.App;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Application.Commands;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Shared.Enums;
using Microsoft.AspNetCore.Http;

namespace UniversalAdmin.Application.Services
{
  public class AppUserServices : IAppUserServices
  {
    private readonly AdminDbContext _db;
    public AppUserServices(AdminDbContext db)
    {
      _db = db;
    }

    public async Task<ApiResult> CreateAsync(CreateUserDto dto)
    {
      // 用户名唯一性校验（忽略大小写和空格）
      var exists = _db.AppUsers.Any(u => u.Username.Trim().ToLower() == dto.Username.Trim().ToLower());
      if (exists)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户名已存在");

      string salt = Guid.NewGuid().ToString("N");
      string hashPwd = HashPassword(dto.Password, salt);

      AppUser user = new()
      {
        Id = Guid.NewGuid(),
        Username = dto.Username,
        Password = hashPwd,
        Email = dto.Email,
        Phone = dto.Phone,
        Avatar = "default-avatar.png", // 后端默认设置默认头像
        AccountStatus = dto.AccountStatus,
        FailedLoginAttempts = dto.FailedLoginAttempts,
        Salt = salt,
        IsActive = true,
        IsDelete = false,
        CreatedAt = DateTime.UtcNow,
        UpdatedAt = DateTime.UtcNow
      };
      // 分配默认普通用户角色
      var defaultRole = _db.AppRoles.FirstOrDefault(r => r.RoleName == "普通用户");
      if (defaultRole == null)
      {
        return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, "系统未配置默认普通用户角色，请联系管理员");
      }
      user.Roles.Add(defaultRole);
      try
      {
        _db.AppUsers.Add(user);
        await _db.SaveChangesAsync();
        return ApiResult.Success("创建用户成功");
      }
      catch (Exception ex)
      {
        var msg = ex.InnerException?.Message ?? ex.Message;
        return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, "数据库写入失败: " + msg);
      }
    }

    public async Task<ApiResult> DeleteAsync(Guid id, Guid? currentUserId = null)
    {
      AppUser? user = await _db.AppUsers.FindAsync(id);
      if (user == null)
        return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
      if (user.IsDelete)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除");

      // 防止删除自己
      if (currentUserId.HasValue && user.Id == currentUserId.Value)
        return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "不能删除自己的账户");

      // 检查用户是否在线（最后活动时间在5分钟内）
      if (user.LastActivityTime.HasValue && 
          user.LastActivityTime.Value > DateTime.UtcNow.AddMinutes(-5))
      {
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, 
          "用户当前在线，请先禁用用户或等待用户离线后再删除");
      }

      user.IsDelete = true;
      _ = _db.AppUsers.Update(user);
      await _db.SaveChangesAsync();
      return ApiResult.Success((int)ApiStatusCode.SUCCESS, "删除成功");
    }

    public async Task<ApiResult<PagedResult<UserDto>>> GetPagedAsync(PagedQuery query)
    {
        var q = _db.AppUsers.Where(u => !u.IsDelete);
        if (!string.IsNullOrWhiteSpace(query.Search))
            q = q.Where(u => u.Username.Contains(query.Search) || (u.Email ?? "").Contains(query.Search));
        var total = await q.CountAsync();
        var items = await q
            .Include(u => u.Roles)
            .OrderByDescending(u => u.CreatedAt)
            .ThenBy(u => u.Id)
            .Skip((query.Page - 1) * query.Size)
            .Take(query.Size)
            .Select(u => new UserDto
            {
                Id = u.Id,
                UserName = u.Username,
                Email = u.Email,
                Phone = u.Phone,
                Avatar = u.Avatar,
                IsActive = u.IsActive,
                Roles = u.Roles.Where(r => !r.IsDelete).Select(r => r.RoleName).ToList()
            })
            .ToListAsync();
        return ApiResult<PagedResult<UserDto>>.Success(200, "操作成功", new PagedResult<UserDto>(items, total, query.Page, query.Size));
    }

    public async Task<ApiResult<IEnumerable<UserDto>>> GetAllAsync(string? search = null)
    {
        var q = _db.AppUsers.Where(u => !u.IsDelete);
        if (!string.IsNullOrWhiteSpace(search))
            q = q.Where(u => u.Username.Contains(search) || (u.Email ?? "").Contains(search));
        var items = await q
            .Include(u => u.Roles)
            .OrderByDescending(u => u.CreatedAt)
            .ThenBy(u => u.Id)
            .Select(u => new UserDto
            {
                Id = u.Id,
                UserName = u.Username,
                Email = u.Email,
                Phone = u.Phone,
                Avatar = u.Avatar,
                IsActive = u.IsActive,
                Roles = u.Roles.Where(r => !r.IsDelete).Select(r => r.RoleName).ToList()
            })
            .ToListAsync();
        return ApiResult<IEnumerable<UserDto>>.Success(200, "操作成功", items.AsEnumerable());
    }

    public async Task<ApiResult<UserDto>> GetByIdAsync(Guid id)
    {
      AppUser? user = await _db.AppUsers.FindAsync(id);
      if (user == null)
        return ApiResult<UserDto>.Failed("用户不存在", (int)ApiStatusCode.NOT_FOUND);
      var dto = new UserDto { 
          Id = user.Id,
          UserName = user.Username, 
          Email = user.Email, 
          Phone = user.Phone,
          Avatar = user.Avatar,
          IsActive = user.IsActive 
      };
      return ApiResult<UserDto>.Success((int)ApiStatusCode.SUCCESS, "操作成功", dto);
    }

    public async Task<ApiResult> UpdateAsync(Guid id, UpdateUserDto dto, Guid? currentUserId = null)
    {
        var user = await _db.AppUsers.FindAsync(id);
        if (user == null)
            return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
        if (user.IsDelete)
            return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除");

        // 检查当前用户是否有管理员权限
        bool isAdmin = false;
        if (currentUserId.HasValue)
        {
            isAdmin = await HasPermissionAsync(currentUserId.Value, "user.manage");
        }

        // 如果不是管理员，只能修改自己的信息
        if (!isAdmin && currentUserId.HasValue && id != currentUserId.Value)
        {
            return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "只能修改自己的信息");
        }

        // 用户名唯一性校验（排除当前用户）
        var exists = _db.AppUsers.Any(u => u.Id != id && u.Username.Trim().ToLower() == dto.UserName.Trim().ToLower());
        if (exists)
            return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户名已存在");

        user.Username = dto.UserName;
        user.Email = dto.Email;
        user.Phone = dto.Phone;
        user.UpdatedAt = DateTime.UtcNow;

        _db.AppUsers.Update(user);
        await _db.SaveChangesAsync();
        return ApiResult.Success("更新成功");
    }

    public async Task<ApiResult> DisableAsync(Guid userId, Guid? currentUserId = null)
    {
      var user = await _db.AppUsers.FindAsync(userId);
      if (user == null)
        return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
      if (user.IsDelete)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除，请确认后重试");
      if (user.IsActive == false)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已是禁用状态");
      
      // 防止用户禁用自己
      if (currentUserId.HasValue && user.Id == currentUserId.Value)
        return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "不能禁用自己的账户");
      
      // 检查用户是否在线（最后活动时间在5分钟内）
      if (user.LastActivityTime.HasValue && 
          user.LastActivityTime.Value > DateTime.UtcNow.AddMinutes(-5))
      {
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, 
          "用户当前在线，请等待用户离线后再禁用");
      }
      
      user.IsActive = false;
      user.AccountStatus = 2; // 设置为管理员禁用状态
      await _db.SaveChangesAsync();
      return ApiResult.Success((int)ApiStatusCode.SUCCESS, "用户已被禁用");
    }

    public async Task<ApiResult> EnableAsync(Guid userId)
    {
      var user = await _db.AppUsers.FindAsync(userId);
      if (user == null)
        return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
      if (user.IsDelete)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除，请确认后重试");
      if (user.IsActive)
        return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已是启用状态");
      user.IsActive = true;
      // 恢复AccountStatus到之前的状态（如果不是管理员禁用，则恢复为正常状态）
      if (user.AccountStatus == 2) // 如果是管理员禁用状态
      {
        user.AccountStatus = 0; // 恢复为正常状态
      }
      // 如果AccountStatus是1（临时锁定），保持原状态，让自动解锁机制处理
      await _db.SaveChangesAsync();
      return ApiResult.Success((int)ApiStatusCode.SUCCESS, "用户已启用");
    }

    public async Task<ApiResult> ChangePasswordAsync(Guid userId, ChangePasswordDto dto, Guid? currentUserId = null)
    {
        var user = await _db.AppUsers.FindAsync(userId);
        if (user == null)
            return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
        if (user.IsDelete)
            return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除");

        // 检查当前用户是否有管理员权限
        bool isAdmin = false;
        if (currentUserId.HasValue)
        {
            isAdmin = await HasPermissionAsync(currentUserId.Value, "user.manage");
        }

        // 如果不是管理员，只能修改自己的密码
        if (!isAdmin && currentUserId.HasValue && userId != currentUserId.Value)
        {
            return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "只能修改自己的密码");
        }

        // 验证旧密码（如果不是管理员修改他人密码，需要验证旧密码）
        if (!isAdmin || (currentUserId.HasValue && userId == currentUserId.Value))
        {
            string oldHashPwd = HashPassword(dto.OldPassword, user.Salt);
            if (user.Password != oldHashPwd)
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "原密码错误");
        }

        // 生成新密码哈希
        string newHashPwd = HashPassword(dto.NewPassword, user.Salt);
        user.Password = newHashPwd;
        user.UpdatedAt = DateTime.UtcNow;

        _db.AppUsers.Update(user);
        await _db.SaveChangesAsync();
        return ApiResult.Success("密码修改成功");
    }

    public async Task<ApiResult> AssignRolesAsync(Guid userId, List<Guid> roleIds)
    {
        var user = await _db.AppUsers.Include(u => u.Roles).FirstOrDefaultAsync(u => u.Id == userId);
        if (user == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
        if (user.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户已被删除");

        var distinctIds = roleIds.Distinct().ToList();
        var roles = _db.AppRoles.Where(r => distinctIds.Contains(r.Id) && !r.IsDelete).ToList();
        if (roles.Count != distinctIds.Count)
            return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "部分角色不存在或已被删除");

        // 覆盖：先清空原有角色
        user.Roles.Clear();
        await _db.SaveChangesAsync(); // 先保存一次，确保数据库已删除所有关联

        // 再分配
        foreach (var role in roles)
            user.Roles.Add(role);

        await _db.SaveChangesAsync();
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "分配角色成功");
    }

    // 权限检查方法
    public async Task<bool> HasPermissionAsync(Guid userId, string permissionCode)
    {
        // 查询用户的所有角色及其权限
        var user = await _db.AppUsers
            .Include(u => u.Roles)
            .ThenInclude(r => r.Permissions)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null) return false;

        // 检查用户角色中是否有指定权限
        return user.Roles.Any(role => 
            role.IsActive && !role.IsDelete && 
            role.Permissions.Any(p => 
                p.IsActive && !p.IsDelete && 
                p.PermissionCode == permissionCode));
    }

    public async Task<IEnumerable<string>> GetUserPermissionsAsync(Guid userId)
    {
        // 查询用户的所有角色及其权限
        var user = await _db.AppUsers
            .Include(u => u.Roles)
            .ThenInclude(r => r.Permissions)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null) return Enumerable.Empty<string>();

        // 返回用户所有角色的所有权限编码
        return user.Roles
            .Where(role => role.IsActive && !role.IsDelete)
            .SelectMany(role => role.Permissions)
            .Where(p => p.IsActive && !p.IsDelete)
            .Select(p => p.PermissionCode)
            .Distinct();
    }

    public async Task<IEnumerable<string>> GetUserRolesAsync(Guid userId)
    {
      var user = await _db.AppUsers.FindAsync(userId);
      if (user == null)
        return Enumerable.Empty<string>();
      return user.Roles.Select(r => r.RoleName);
    }

    public async Task<IEnumerable<RoleDto>> GetUserRolesDetailAsync(Guid userId)
    {
      var user = await _db.AppUsers.Include(u => u.Roles).FirstOrDefaultAsync(u => u.Id == userId);
      if (user == null) return Enumerable.Empty<RoleDto>();
      return user.Roles
          .Where(r => !r.IsDelete)
          .Select(r => new RoleDto
          {
              Id = r.Id,
              RoleName = r.RoleName,
              Description = r.Description,
              IsActive = r.IsActive
          })
          .ToList();
    }

    public async Task<ApiResult> UploadAvatarAsync(Guid userId, IFormFile file, Guid? currentUserId = null)
    {
        try
        {
            // 检查用户是否存在
            var user = await _db.AppUsers.FirstOrDefaultAsync(u => u.Id == userId && !u.IsDelete);
            if (user == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "用户不存在");
            }

            // 检查用户是否只能修改自己的头像
            if (currentUserId.HasValue && userId != currentUserId.Value)
            {
                // 检查当前用户是否有管理员权限
                bool isAdmin = await HasPermissionAsync(currentUserId.Value, "user.manage");
                if (!isAdmin)
                {
                    return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "只能修改自己的头像");
                }
            }

            // 验证文件类型（只允许图片）
            if (!IsValidImageFile(file))
            {
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "只支持图片格式：jpg、jpeg、png、gif、bmp");
            }

            // 验证文件大小（限制为2MB）
            if (file.Length > 2 * 1024 * 1024)
            {
                return ApiResult.Failed((int)ApiStatusCode.BAD_REQUEST, "头像文件大小不能超过2MB");
            }

            // 删除旧头像文件（如果存在且不是默认头像）
            await DeleteOldAvatarIfExists(user);

            // 保存新头像文件
            var (filePath, fileName) = await SaveAvatarFile(userId, file);

            // 更新用户头像字段
            user.Avatar = fileName; // 只存储文件名
            user.UpdatedAt = DateTime.UtcNow;

            // 保存到数据库
            _db.AppUsers.Update(user);
            await _db.SaveChangesAsync();

            return ApiResult.Success("头像上传成功", new { avatar = fileName });
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"上传头像失败: {ex.Message}");
        }
    }

    // 验证是否为有效的图片文件
    private bool IsValidImageFile(IFormFile file)
    {
        var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };
        var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
        return allowedExtensions.Contains(fileExtension);
    }

    // 删除旧头像文件（如果存在且不是默认头像）
    private async Task DeleteOldAvatarIfExists(AppUser user)
    {
        if (!string.IsNullOrEmpty(user.Avatar) && 
            !user.Avatar.Equals("default-avatar.png", StringComparison.OrdinalIgnoreCase))
        {
            var oldAvatarPath = Path.Combine("uploads", "avatars", user.Avatar);
            var oldFullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", oldAvatarPath);
            if (System.IO.File.Exists(oldFullPath))
            {
                System.IO.File.Delete(oldFullPath);
            }
        }
    }

    // 保存头像文件到磁盘
    private async Task<(string filePath, string fileName)> SaveAvatarFile(Guid userId, IFormFile file)
    {
        var fileName = $"avatar_{userId}_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
        var filePath = Path.Combine("uploads", "avatars", fileName);
        var fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", filePath);

        // 确保目录存在
        var directory = Path.GetDirectoryName(fullPath);
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory!);
        }

        // 确保文件路径安全
        var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
        var extension = Path.GetExtension(fileName);
        
        // 如果文件名包含不安全字符，重新生成
        if (fileNameWithoutExtension.Contains("..") || fileNameWithoutExtension.Contains("/") || fileNameWithoutExtension.Contains("\\"))
        {
            fileName = $"avatar_{userId}_{Guid.NewGuid()}{extension}";
            filePath = Path.Combine("uploads", "avatars", fileName);
            fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", filePath);
        }

        // 保存文件到磁盘
        using (var stream = new FileStream(fullPath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        return (filePath, fileName);
    }

    // 获取头像文件名（确保只返回文件名而不是路径）
    private string GetAvatarFileName(string? avatar)
    {
        if (string.IsNullOrEmpty(avatar))
        {
            return "default-avatar.png";
        }

        // 如果包含路径分隔符，提取文件名
        if (avatar.Contains('/') || avatar.Contains('\\'))
        {
            return Path.GetFileName(avatar);
        }

        // 如果已经是文件名，直接返回
        return avatar;
    }
    private static string HashPassword(string password, string salt)
    {
      // 简单示例，实际请用更安全的哈希算法
      byte[] bytes = System.Text.Encoding.UTF8.GetBytes(password + salt);
      byte[] hash = System.Security.Cryptography.SHA256.HashData(bytes);
      return Convert.ToBase64String(hash);
    }
    
  }

}